home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / os2 / plnk081.zip / pilot-link.0.8.1 / libsock / inet.c < prev    next >
C/C++ Source or Header  |  1997-08-05  |  9KB  |  368 lines

  1. /* inet.c: Interface layer to TCP/IP NetSync connections
  2.  *
  3.  * Copyright (c) 1997, Kenneth Albanowski
  4.  * This is free software, licensed under the GNU Public License V2.
  5.  * See the file COPYING for details.
  6.  */
  7.  
  8. #include <sys/types.h>
  9. #include <sys/stat.h>
  10. #include <netinet/in.h>
  11. #include <arpa/inet.h>
  12. #include <netdb.h>
  13. #include <stdio.h>
  14. #include "pi-source.h"
  15. #include "pi-socket.h"
  16. #include "pi-inet.h"
  17. #include "pi-slp.h"
  18. #include "pi-syspkt.h"
  19. #include "pi-padp.h"
  20. #include "pi-dlp.h"
  21.  
  22. static int pi_net_listen(struct pi_socket *ps, int backlog);
  23. static int pi_net_accept(struct pi_socket *ps, struct sockaddr *addr, int *addrlen);
  24. static int pi_net_send(struct pi_socket *ps, void *msg, int len, unsigned int flags);
  25. static int pi_net_recv(struct pi_socket *ps, void *msg, int len, unsigned int flags);
  26. static int pi_net_tickle(struct pi_socket *ps);
  27. static int pi_net_close(struct pi_socket * ps);
  28.  
  29. extern int dlp_trace;
  30.  
  31. int pi_inet_connect(struct pi_socket *ps, struct sockaddr *addr, int addrlen)
  32. {
  33.   struct sockaddr_in serv_addr;
  34.   char msg1[22] = "\x90\x01\x00\x00\x00\x00\x00\x00\x00\x20\x00\x00\x00\x08\x01\x00\x00\x00\x00\x00\x00\x00";
  35.   char msg2[50] = 
  36. "\x92\x01\x00\x00\x00\x00\x00\x00\x00\x20\
  37. \x00\x00\x00\x24\xff\xff\xff\xff\x00\x3c\x00\x3c\x40\x00\x00\x00\
  38. \x01\x00\x00\x00\xc0\xa8\xa5\x1e\x04\x01\x00\x00\x00\x00\x00\x00\
  39. \x00\x00\x00\x00\x00\x00\x00\x00";
  40.   char msg3[8] = "\x93\x00\x00\x00\x00\x00\x00\x00";
  41.   char buffer[200];
  42.  
  43.   ps->mac->fd = socket(AF_INET, SOCK_STREAM, 0);
  44.  
  45.   if (ps->sd) {
  46.     int orig = ps->mac->fd;
  47. #ifdef HAVE_DUP2
  48.     ps->mac->fd = dup2(ps->mac->fd, ps->sd);
  49. #else
  50. #ifdef F_DUPFD
  51.     close(ps->sd);
  52.     ps->mac->fd = fcntl(ps->mac->fd, F_DUPFD, ps->sd);
  53. #else
  54.     close(ps->sd);
  55.     ps->mac->fd = dup(ps->mac->fd); /* Unreliable */
  56. #endif
  57. #endif
  58.     if (ps->mac->fd != orig)
  59.       close(orig);
  60.   }
  61.  
  62.   if (addr->sa_family == AF_INET) {
  63.     memcpy(&serv_addr, addr, addrlen);
  64.   } else {
  65.     struct pi_sockaddr * paddr = (struct pi_sockaddr*)addr;
  66.     char * device = paddr->pi_device+1;
  67.     memset(&serv_addr, 0, sizeof(serv_addr));
  68.     serv_addr.sin_family = AF_INET;
  69.     serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  70.     serv_addr.sin_port = htons(14238);
  71.     if (strlen(device)>1) {
  72.       if ((serv_addr.sin_addr.s_addr = inet_addr(device))==-1) {
  73.         struct hostent * hostent = gethostbyname(device);
  74.         if (!hostent) {
  75.           fprintf(stderr, "Unable to resolve host '%s'", device);
  76.           return -1;
  77.         }
  78.         memcpy((char*)&serv_addr.sin_addr.s_addr, hostent->h_addr,hostent->h_length);
  79.       }
  80.     }
  81.   }
  82.   
  83.  
  84.   if (connect(ps->mac->fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr))<0)
  85.     return -1;
  86.  
  87.   ps->socket_listen = pi_net_listen;
  88.   ps->socket_accept = pi_net_accept;
  89.   ps->socket_send = pi_net_send;
  90.   ps->socket_recv = pi_net_recv;
  91.   ps->socket_tickle= pi_net_tickle;
  92.   ps->socket_close = pi_net_close;
  93.  
  94.   ps->initiator = 1;
  95.  
  96.   pi_net_send(ps, msg1, 22, 0);
  97.   pi_net_recv(ps, buffer, 200, 0);
  98.   pi_net_send(ps, msg2, 50, 0);
  99.   pi_net_recv(ps, buffer, 200, 0);
  100.   pi_net_send(ps, msg3, 8, 0);
  101.  
  102. #ifndef NO_SERIAL_TRACE
  103.   if(ps->debuglog) {
  104.     ps->debugfd = open(ps->debuglog,O_WRONLY|O_CREAT|O_APPEND,0666);
  105.     /* This sequence is magic used by my trace analyzer - kja */
  106.     write(ps->debugfd, "\0\2\0\0\0\0\0\0\0\0", 10);
  107.   }
  108. #endif
  109.   
  110.   return 0;
  111. }
  112.  
  113. /* Bind address to a local socket */
  114.  
  115. int pi_inet_bind(struct pi_socket *ps, struct sockaddr *addr, int addrlen)
  116. {
  117.   int opt, optlen;
  118.   struct sockaddr_in serv_addr;
  119.   ps->mac->fd = socket(AF_INET, SOCK_STREAM, 0);
  120.  
  121.   if (ps->sd) {
  122.     int orig = ps->mac->fd;
  123. #ifdef HAVE_DUP2
  124.     ps->mac->fd = dup2(ps->mac->fd, ps->sd);
  125. #else
  126. #ifdef F_DUPFD
  127.     close(ps->sd);
  128.     ps->mac->fd = fcntl(ps->mac->fd, F_DUPFD, ps->sd);
  129. #else
  130.     close(ps->sd);
  131.     ps->mac->fd = dup(ps->mac->fd); /* Unreliable */
  132. #endif
  133. #endif
  134.     if (ps->mac->fd != orig)
  135.       close(orig);
  136.     else {
  137.       puts("Unable to duplicate socket");
  138.       exit(1);
  139.     }
  140.   }
  141.  
  142.   if (addr->sa_family == AF_INET) {
  143.     memcpy(&serv_addr, addr, addrlen);
  144.   } else {
  145.     struct pi_sockaddr * paddr = (struct pi_sockaddr*)addr;
  146.     char * device = paddr->pi_device+1;
  147.     memset(&serv_addr, 0, sizeof(serv_addr));
  148.     serv_addr.sin_family = AF_INET;
  149.     serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  150.     serv_addr.sin_port = htons(14238);
  151.     if (strlen(device)>1) {
  152.       if ((serv_addr.sin_addr.s_addr = inet_addr(device))==-1) {
  153.         struct hostent * hostent = gethostbyname(device);
  154.         if (!hostent) {
  155.           fprintf(stderr, "Unable to resolve host '%s'", device);
  156.           return -1;
  157.         }
  158.         memcpy((char*)&serv_addr.sin_addr.s_addr, hostent->h_addr,hostent->h_length);
  159.       }
  160.     }
  161.   }
  162.  
  163.   opt=1;
  164.   optlen=sizeof(opt);
  165.   if (setsockopt(ps->sd, SOL_SOCKET, SO_REUSEADDR, &opt, optlen)<0) {
  166.     return -1;
  167.   }
  168.  
  169.   if (bind(ps->sd, (struct sockaddr*)&serv_addr, sizeof(serv_addr))<0)
  170.     return -1;
  171.  
  172. #ifndef NO_SERIAL_TRACE
  173.   if(ps->debuglog) {
  174.     ps->debugfd = open(ps->debuglog,O_WRONLY|O_CREAT|O_APPEND,0666);
  175.     /* This sequence is magic used by my trace analyzer - kja */
  176.     write(ps->debugfd, "\0\2\0\0\0\0\0\0\0\0", 10);
  177.   }
  178. #endif
  179.  
  180.   ps->socket_listen = pi_net_listen;
  181.   ps->socket_accept = pi_net_accept;
  182.   ps->socket_send = pi_net_send;
  183.   ps->socket_recv = pi_net_recv;
  184.   ps->socket_tickle= pi_net_tickle;
  185.   ps->socket_close = pi_net_close;
  186.  
  187.   ps->initiator = 0;
  188.  
  189.   return 0;
  190. }
  191.  
  192. /* Wait for an incoming connection */
  193.  
  194. static int pi_net_listen(struct pi_socket *ps, int backlog)
  195. {
  196.   return listen(ps->sd, backlog);
  197. }
  198.  
  199. /* Accept an incoming connection */
  200.  
  201. static int pi_net_accept(struct pi_socket *ps, struct sockaddr *addr, int *addrlen)
  202. {
  203.   struct pi_socket *a;
  204.   char msg1[50] = 
  205. "\x12\x01\x00\x00\x00\x00\x00\x00\x00\x20\x00\x00\x00\x24\xff\xff\
  206. \xff\xff\x3c\x00\x3c\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc0\xa8\
  207. \xa5\x1f\x04\x27\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
  208. \x00\x00";
  209.   char msg2[46] =
  210. "\x13\x01\x00\x00\x00\x00\x00\x00\x00\x20\x00\x00\x00\x20\xff\xff\
  211. \xff\xff\x00\x3c\x00\x3c\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\
  212. \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
  213.   char buffer[200];
  214.  
  215.   a = malloc(sizeof(struct pi_socket));
  216.   memcpy(a, ps, sizeof(struct pi_socket));
  217.   
  218.  
  219.   a->sd = accept(ps->sd, addr, addrlen);
  220.   if (a->sd < 0)
  221.     goto fail;
  222.  
  223.   pi_net_recv(a, buffer, 200, 0);
  224.   pi_net_send(a, msg1, 50, 0);
  225.   pi_net_recv(a, buffer, 200, 0);
  226.   pi_net_send(a, msg2, 46, 0);
  227.   pi_net_recv(a, buffer, 200, 0);
  228.  
  229.   pi_socket_recognize(a);
  230.   
  231.   a->connected = 1;
  232.  
  233.   return a->sd;
  234. fail:
  235.   free(a);
  236.   return -1;
  237. }
  238.  
  239. /* Send msg on a connected socket */
  240.  
  241. static int pi_net_send(struct pi_socket *ps, void *msg, int len, unsigned int flags)
  242. {
  243.   int n,l;
  244.   unsigned char buf[6];
  245.   buf[0] = 1;
  246.   buf[1] = ps->xid;
  247.   set_long(buf+2, len);
  248.   
  249.   l = 0;
  250.   while (l<6) {
  251.     n = write(ps->sd, buf+l, 6-l);
  252.     if (n>0)
  253.       l += n;
  254.     if (n<0)
  255.       return n;
  256.   }
  257.   
  258.   l = 0;
  259.   while (l<len) {
  260.     n = write(ps->sd, (char *)msg+l, len-l);
  261.     if (n>0)
  262.       l += n;
  263.     if (n<0)
  264.       return n;
  265.   }
  266.  
  267. #ifndef NO_SERIAL_TRACE
  268.   if (ps->debuglog) {
  269.     buf[0] = 4;
  270.     buf[1] = 0;
  271.     set_long(buf+2, len);
  272.     write(ps->debugfd, buf, 6);
  273.     write(ps->debugfd, msg, len);
  274.   }
  275. #endif
  276.   
  277.   return len;
  278. }
  279.  
  280. /* Recv msg on a connected socket */
  281.  
  282. static int pi_net_recv(struct pi_socket *ps, void *msg, int len, unsigned int flags)
  283. {
  284.   int n,l;
  285.   int rlen;
  286.   unsigned char buf[6];
  287.   
  288.   l = 0;
  289.   while (l<6) {
  290.     n = read(ps->sd, buf+l, 6-l);
  291.     if (n>0)
  292.       l += n;
  293.     if (n<0)
  294.       return n;
  295.   }
  296.   
  297.   rlen = get_long(buf+2);
  298.   
  299.   if (len>rlen)
  300.     len=rlen;
  301.   
  302.   l = 0;
  303.   while (l<len) {
  304.     n = read(ps->sd, (char *)msg+l, len-l);
  305.     if (n>0)
  306.       l += n;
  307.     if (n<0)
  308.       return n;
  309.   }
  310.  
  311.   if (l<rlen) {
  312.     char discard;
  313.     while (l<rlen) {
  314.       n = read(ps->sd, &discard, 1);
  315.       if (n>0)
  316.         l += n;
  317.       if (n<0)
  318.         return n;
  319.     }
  320.   }
  321.  
  322.   if (ps->initiator)
  323.     ps->xid = buf[1];
  324.   else {
  325.     ps->xid++;
  326.     if (ps->xid == 0xff)
  327.       ps->xid = 1;
  328.   }
  329.  
  330. #ifndef NO_SERIAL_TRACE
  331.   if (ps->debuglog) {
  332.     buf[0] = 3;
  333.     buf[1] = 0;
  334.     set_long(buf+2, len);
  335.     write(ps->debugfd, buf, 6);
  336.     write(ps->debugfd, msg, len);
  337.   }
  338. #endif
  339.   
  340.   return len;
  341. }
  342.  
  343. static int pi_net_tickle(struct pi_socket *ps)
  344. {
  345.   return -1;
  346. }
  347.  
  348. /* Close a connection, destroy the socket */
  349.  
  350. static int pi_net_close(struct pi_socket * ps)
  351. {
  352.   if (ps->type == PI_SOCK_STREAM) {
  353.     if (ps->connected & 1) /* If socket is connected */
  354.       if (!(ps->connected & 2)) /* And it wasn't end-of-synced */
  355.         dlp_EndOfSync(ps->sd, 0);  /* then end sync, with clean status */
  356.   }
  357.   
  358.   close(ps->sd);
  359.  
  360. #ifndef NO_SERIAL_TRACE
  361.   if (ps->debugfd)
  362.     close(ps->debugfd);
  363. #endif
  364.  
  365.   return 0;
  366. }
  367.  
  368.